package com.sh.data.engine.repository.dao.normalization.standard;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sh.data.engine.repository.dao.normalization.standard.arg.DictionaryArg;
import com.sh.data.engine.repository.dao.normalization.standard.entity.DictionaryEntity;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Repository;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author jingchen.hr
 */
@Repository
public interface DictionaryMapper extends BaseMapper<DictionaryEntity> {

    /**
     * 字典列表查询(分页)
     *
     * @param projectId
     * @param dictDirIds
     * @param search
     * @param releaseStatus
     * @param orderField    排序字段必传
     * @param order         排序方式必传
     * @return
     */
    default IPage<DictionaryEntity> queryList(
        Long projectId,
        List<Long> dictDirIds,
        String search,
        Integer releaseStatus,
        String orderField,
        String order,
        Integer pageSize,
        Integer pageNum) {
        //    Page<Object> objects = PageHelper.startPage(pageNum, pageSize);
        LambdaQueryWrapper<DictionaryEntity> query = new QueryWrapper<DictionaryEntity>().lambda();
        query
            .eq(DictionaryEntity::getRowState, 1)
            .eq(DictionaryEntity::getProjectId, projectId)
            .in(
                CollectionUtils.isNotEmpty(dictDirIds),
                DictionaryEntity::getDictDirId,
                dictDirIds)
            .eq(Objects.nonNull(releaseStatus), DictionaryEntity::getReleaseStatus, releaseStatus)
            .and(
                Objects.nonNull(search),
                i ->
                    i.like(DictionaryEntity::getDictNameEn, search)
                        .or()
                        .like(DictionaryEntity::getDictNameCn, search))
            .orderByDesc(DictionaryEntity::getId);
        if (Objects.equals(orderField, "updateTime")) {
            if (StringUtils.isBlank(order)) {
                query.orderByDesc(DictionaryEntity::getUpdateTime);
            } else {
                query.orderByAsc(DictionaryEntity::getUpdateTime);
            }
        } else if (Objects.equals(orderField, "dictNameEn")) {
            if (StringUtils.isBlank(order)) {
                query.orderByDesc(DictionaryEntity::getDictNameEn);
            } else {
                query.orderByAsc(DictionaryEntity::getDictNameEn);
            }
        }
        Page<DictionaryEntity> page =
            this.selectPage(new Page<DictionaryEntity>(pageNum, pageSize), query);
        //    long total = objects.getTotal();
        //    PageInfo<DictionaryEntity> pageInfo = new PageInfo<>();
        //    pageInfo.setList(list);
        //    pageInfo.setTotal(total);
//        PageResult<DictionaryEntity> result = new PageResult<>();
//        result.setTotalElements(page.getTotal());
//        result.setResult(page.getRecords());
//        result.setPageNum(pageNum);
//        result.setPageSize(pageSize);
//        result.setTotalPages(Math.toIntExact(page.getPages()));
        return page;
    }

    /**
     * 根据id查询
     *
     * @param id
     * @return
     */
    default DictionaryEntity getById(Long id) {

        LambdaQueryWrapper<DictionaryEntity> query = new QueryWrapper<DictionaryEntity>().lambda();
        query.eq(DictionaryEntity::getId, id).eq(DictionaryEntity::getRowState, 1);
        return this.selectOne(query);
    }

    default List<DictionaryEntity> getDicDetail(Long projectId) {

        LambdaQueryWrapper<DictionaryEntity> query = new QueryWrapper<DictionaryEntity>().lambda();
        query.eq(DictionaryEntity::getProjectId, projectId).eq(DictionaryEntity::getRowState, 1);

        return this.selectList(query);
    }

    /**
     * 按条件统计记录数
     *
     * @param arg
     * @return
     */
    default List<DictionaryEntity> getListByArg(DictionaryArg arg) {

        LambdaQueryWrapper<DictionaryEntity> query = new QueryWrapper<DictionaryEntity>().lambda();
        query
            .eq(DictionaryEntity::getRowState, 1)
            .eq(DictionaryEntity::getProjectId, arg.getProjectId())
            .and(
                i ->
                    i.eq(DictionaryEntity::getDictNameEn, arg.getDictNameEn())
                        .or()
                        .eq(DictionaryEntity::getDictNameCn, arg.getDictNameCn()));
        return this.selectList(query);
    }

    /**
     * 根据目录id查字典
     *
     * @param dictDirIds
     * @return
     */
    default List<DictionaryEntity> getListByDictDirIds(List<Long> dictDirIds) {
        if (CollectionUtils.isEmpty(dictDirIds)) {
            return Collections.EMPTY_LIST;
        }

        LambdaQueryWrapper<DictionaryEntity> query = new QueryWrapper<DictionaryEntity>().lambda();
        query.eq(DictionaryEntity::getRowState, 1).in(DictionaryEntity::getDictDirId, dictDirIds);
        return this.selectList(query);
    }

    default List<DictionaryEntity> getDictionaryByProjectIdAndLastTaskTime(
        Long projectId, Date lastTaskExecuteTime, Date currentTaskExecuteTime) {

        // fixme 待验证
        LambdaQueryWrapper<DictionaryEntity> query = new QueryWrapper<DictionaryEntity>().lambda();
        query
            .eq(DictionaryEntity::getProjectId, projectId)
            .and(
                Objects.isNull(lastTaskExecuteTime),
                i ->
                    i.eq(DictionaryEntity::getRowState, 1)
                        .eq(DictionaryEntity::getReleaseStatus, 1)
                        .lt(DictionaryEntity::getCreateTime, currentTaskExecuteTime))
            .and(
                Objects.nonNull(lastTaskExecuteTime),
                i ->
                    i.eq(DictionaryEntity::getRowState, 1)
                        .lt(DictionaryEntity::getCreateTime, currentTaskExecuteTime)
                        .ge(DictionaryEntity::getCreateTime, currentTaskExecuteTime)
                        .or(
                            i2 ->
                                i2.lt(DictionaryEntity::getCreateTime, lastTaskExecuteTime)
                                    .ge(DictionaryEntity::getReleaseTime, lastTaskExecuteTime)
                                    .eq(DictionaryEntity::getRowState, 1))
                        .or(
                            i3 ->
                                i3.lt(DictionaryEntity::getCreateTime, lastTaskExecuteTime)
                                    .ge(DictionaryEntity::getUpdateTime, lastTaskExecuteTime)
                                    .eq(DictionaryEntity::getRowState, 0)));

        return this.selectList(query);
    }

    /**
     * 根据ids查字典
     *
     * @param ids
     * @return
     */
    default Map<Long, DictionaryEntity> getMapByIds(List<Long> ids) {
        return getListByIds(ids).stream()
            .collect(Collectors.toMap(DictionaryEntity::getId, Function.identity()));
    }

    /**
     * 获取中文名列表
     *
     * @param projectId
     * @return
     */
    default List<String> getDictNameCnByProjectId(Long projectId) {

        LambdaQueryWrapper<DictionaryEntity> query = new QueryWrapper<DictionaryEntity>().lambda();
        query.eq(DictionaryEntity::getRowState, 1).eq(DictionaryEntity::getProjectId, projectId);
        List<DictionaryEntity> multi = this.selectList(query);
        Set<String> set =
            multi.stream().map(DictionaryEntity::getDictNameCn).collect(Collectors.toSet());

        return set.stream().collect(Collectors.toList());
    }

    /**
     * 获取英文名列表
     *
     * @param projectId
     * @return
     */
    default List<String> getDictNameEnByProjectId(Long projectId) {

        LambdaQueryWrapper<DictionaryEntity> query = new QueryWrapper<DictionaryEntity>().lambda();
        query.eq(DictionaryEntity::getRowState, 1).eq(Objects.nonNull(projectId), DictionaryEntity::getProjectId, projectId);
        List<DictionaryEntity> multi = this.selectList(query);
        Set<String> set =
            multi.stream().map(DictionaryEntity::getDictNameEn).collect(Collectors.toSet());

        return set.stream().collect(Collectors.toList());
    }

    /**
     * 根据id查字典
     *
     * @param ids
     * @return
     */
    default List<DictionaryEntity> getListByIds(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return Collections.emptyList();
        }

        LambdaQueryWrapper<DictionaryEntity> query = new QueryWrapper<DictionaryEntity>().lambda();
        query.eq(DictionaryEntity::getRowState, 1).in(DictionaryEntity::getId, ids);
        return this.selectList(query);
    }

    /**
     * 批量删除
     *
     * @param ids
     * @param userId
     * @param date
     */
    default void deleteByIds(List<Long> ids, String userId, Date date) {

        LambdaUpdateWrapper<DictionaryEntity> update = new UpdateWrapper<DictionaryEntity>().lambda();
        update
            .eq(DictionaryEntity::getRowState, 1)
            .in(DictionaryEntity::getId, ids)
            .set(DictionaryEntity::getRowState, 0)
            .set(DictionaryEntity::getUpdateTime, date)
            .set(DictionaryEntity::getUpdaterId, userId);
        this.update(null, update);
    }

    /**
     * 批量发布/下线
     *
     * @param ids
     * @param userId
     * @param releaseStatus
     * @param date
     */
    default void releaseByIds(List<Long> ids, String userId, int releaseStatus, Date date) {
        LambdaUpdateWrapper<DictionaryEntity> update = new UpdateWrapper<DictionaryEntity>().lambda();
        update
            .eq(DictionaryEntity::getRowState, 1)
            .in(DictionaryEntity::getId, ids)
            .set(DictionaryEntity::getUpdateTime, date)
            .set(DictionaryEntity::getReleaseTime, date)
            .set(DictionaryEntity::getUpdaterId, userId)
            .set(DictionaryEntity::getReleaseStatus, releaseStatus);
        this.update(null, update);
    }
}
